package net.sureon.web;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sureon.app.AppContext;
import net.sureon.app.UserSession;
import net.sureon.biz.CompanyBO;
import net.sureon.biz.CompanyMgr;
import net.sureon.biz.UserBO;
import net.sureon.biz.UserMgr;
import net.sureon.common.SureonConstants;
import net.sureon.common.exception.ExceptionKeys;
import net.sureon.common.exception.SureonException;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class Login implements Controller {

    private static final Log logger = LogFactory.getLog(Login.class);
    private String loginFailPage;
    private String firstPage;
    private String systemAdminPage;
    private CompanyMgr companyMgr;
    private UserMgr userMgr;

    public ModelAndView handleRequest(HttpServletRequest request,
        HttpServletResponse response) throws Exception {
        AppCookie appCookie = new AppCookie(request.getCookies());
        Object siteUrlAttr = request.getAttribute(SureonConstants.REQ_ATTR_SITEURL);
        if(siteUrlAttr != null){
        	appCookie.setSiteURL((String) siteUrlAttr);
        }
        boolean success = false;
        if (!StringUtils.isEmpty(appCookie.getToken())) {
            success = verifyToken(response, appCookie);
        }
        if (!success) {
            String userName = request.getParameter("userName");
            String siteURL;
            Object o = request.getAttribute(SureonConstants.REQ_ATTR_SITEURL);
            if (o != null) {
                siteURL = (String) o;
            } else {
                siteURL = request.getParameter("siteURL");
            }
            String password = request.getParameter("password");
            if (SureonConstants.CHECK_BOX_OPTION_ON.equals(request
                .getParameter("saveCompany"))) {

                appCookie.setSiteURL(siteURL);
                appCookie.saveSiteURL(response);
            }
            if (SureonConstants.CHECK_BOX_OPTION_ON.equals(request
                .getParameter("saveUserName"))) {
                appCookie.setUserName(userName);
                appCookie.saveUserName(response);
            }
            if (userName != null && password != null) {
                try{
                	success = verifyPassword(request, siteURL, userName, password);
                }catch(SureonException e){
                	logger.error(e);
                }
            }

        }
        if (success) {
            return processSuccess(request, response, appCookie);
        } else {
            return processFailure(request, response);
        }
    }

    private ModelAndView processSuccess(HttpServletRequest request,
        HttpServletResponse response, AppCookie appCookie) throws Exception {

        UserSession currentSession = AppContext.getCurrentUserSession();

        UserBO user = userMgr.getUser(currentSession.getCompanyID(),
            currentSession.getUserID());

        request.getSession().setAttribute(UserSession.HTTP_SESSION_KEY,
            currentSession);
        if (SureonConstants.CHECK_BOX_OPTION_ON.equals(request
            .getParameter("savePassword"))) {
            appCookie.setToken(user.generateUserToken());
            appCookie.setUserID(currentSession.getUserID());
            if(!currentSession.isRootLogin()){
                appCookie.setSiteURL(companyMgr.getCompany(AppContext.getCompanyID()).getCompanyVO().getSiteURL());
                appCookie.saveSiteURL(response);
            }
            appCookie.saveToken(response);
        }
        String jumpTo = null;
        if(AppContext.isRootLogin()){
            jumpTo = getSystemAdminPage();
        }else{
            jumpTo = getFirstPage();
        }
        response.sendRedirect(request.getContextPath()
            + jumpTo);
        return null;
    }

    private ModelAndView processFailure(HttpServletRequest request,
        HttpServletResponse response) throws Exception {
        ModelAndView view = new ModelAndView();
        view.setViewName(this.getLoginFailPage());
        if(request.getAttribute("loginFailure") == null){
        	request.setAttribute("loginFailure", "用户名/密码不正确，请重新输入！");
        }
        return view;
    }

    /**
     * @return the loginFailPage
     */
    public String getLoginFailPage() {
        return loginFailPage;
    }

    /**
     * @param loginFailPage
     *            the loginFailPage to set
     */
    public void setLoginFailPage(String loginFailPage) {
        this.loginFailPage = loginFailPage;
    }

    /**
     * @return the companyMgr
     */
    public CompanyMgr getCompanyMgr() {
        return companyMgr;
    }

    /**
     * @param companyMgr
     *            the companyMgr to set
     */
    public void setCompanyMgr(CompanyMgr companyMgr) {
        this.companyMgr = companyMgr;
    }

    /**
     * @return the firstPage
     */
    public String getFirstPage() {
        return firstPage;
    }

    /**
     * @param firstPage the firstPage to set
     */
    public void setFirstPage(String firstPage) {
        this.firstPage = firstPage;
    }

    /**
     * @return the systemAdminPage
     */
    public String getSystemAdminPage() {
        return systemAdminPage;
    }

    /**
     * @param systemAdminPage the systemAdminPage to set
     */
    public void setSystemAdminPage(String systemAdminPage) {
        this.systemAdminPage = systemAdminPage;
    }

    /**
     * @return the userMgr
     */
    public UserMgr getUserMgr() {
        return userMgr;
    }

    /**
     * @param userMgr
     *            the userMgr to set
     */
    public void setUserMgr(UserMgr userMgr) {
        this.userMgr = userMgr;
    }

    private boolean verifyToken(HttpServletResponse response, AppCookie cookie)
        throws SureonException {
        long companyID = AppContext.getCompanyID();
        String siteURL = cookie.getSiteURL();
        if(StringUtils.isNotEmpty(siteURL)){
            CompanyBO company = companyMgr.getCompany(siteURL);
            companyID = company.getCompanyID();
        }
        UserBO user = userMgr.getUser(companyID, cookie
            .getUserID());
        boolean verified = user.verifyToken(cookie.getToken());
        if (verified) {
            AppContext.setCurrentUserSession(new UserSession(user));
        } else {
            cookie.resetToken(response);
        }
        return verified;
    }

    private boolean verifyPassword(HttpServletRequest request, String siteURL, String userName,
        String password) throws SureonException {
        UserBO user = userMgr.getUserByUsername(0,
            userName);
        if (logger.isDebugEnabled()) {
            logger.debug("user found, userID="
                + user.getUserVO().getUserID());
        }
        if (!user.isActive()) {
            logger.error("user inactive, userid=" + user.getUserID()
                + ", username=" + userName + ", siteurl=" + siteURL);
            throw new SureonException(ExceptionKeys.USER_INACTIVE, userName);
        }
        boolean verified = user.verifyPassword(password);
        if (verified) {  
            AppContext.setCurrentUserSession(new UserSession(user));
            if(user.getCompanyID() > 0){
                CompanyBO company = companyMgr.getCompany(user.getCompanyID());
                if (!StringUtils.isEmpty(siteURL)) {
                    if(!siteURL.equalsIgnoreCase(company.getCompanyVO().getSiteURL())){
                        logger.error("siteurl does not match, input=" + siteURL + ", DB=" + company.getCompanyVO().getSiteURL());
                        return false;
                    }
                }
                if (company.getCompanyVO().getValidDate().before(new Date())) {
                    logger.error("company invalid, companyID="
                        + company.getCompanyID() + ", siteurl=" + siteURL);
                    request.setAttribute("loginFailure", "对不起，贵公司账号已冻结， 请联系管理员！");
                    throw new SureonException(ExceptionKeys.SITE_INVALIID, siteURL);
                }
            }
            return true;
        }
        return false;
    }

}